# 省会城市天气信息获取
import pandas as pd  # 导入pandas库，用于处理和分析数据
import requests  # 导入requests库，用于发送HTTP请求
from bs4 import BeautifulSoup  # 导入BeautifulSoup库，用于解析HTML文档
import csv  # 导入csv库，用于读写CSV文件


def getHTMLtext(url):
    """
    获取指定URL的HTML内容
    :param url: 目标URL地址
    :return: HTML内容，若请求错误则返回空字符集
    """
    try:
        r = requests.get(url, timeout=30)  # 发送GET请求
        r.raise_for_status()  # 检查响应状态码，若错误则抛出异常
        r.encoding = r.apparent_encoding  # 根据响应内容分析编码方式
        print("成功访问")
        return r.text  # 返回HTML内容
    except:
        print("访问错误")
        return " "


def get_content(html, city):
    """
    提取HTML内容中的天气内容
    :param html: HTML内容
    :param city: 城市内容
    :return: 返回一个列表，每个元素包含城市、日期、天气、最低气温、最高气温、风向1、风向2、风级的子列表
    """
    final = []  # 初始化一个列表保存数据
    bs = BeautifulSoup(html, "html.parser")  # 创建BeautifulSoup对象
    body = bs.body
    data = body.find('div', {'id': '7d'})  # 找到div标签且id = 7d # 下面爬取当天的数据

    # 下面爬取7天的数据
    ul = data.find('ul')  # 找到所有的ul标签
    li = ul.find_all('li')  # 找到左右的li标签
    i = 0  # 控制爬取的天数
    for day in li:  # 遍历找到的每一个li
        temp = [city]  # 临时存放每天的数据
        date = day.find('h1').string  # 得到日期
        date = date[0:date.index('日')]  # 取出日期号
        temp.append(date)
        inf = day.find_all('p')  # 找出li下面的p标签,提取第一个p标签的值，即天气
        temp.append(inf[0].string)  # 天气
        tem_low = inf[1].find('i').string  # 找到最低气温

        if inf[1].find('span') is None:  # 天气预报可能没有最高气温
            tem_high = None
        else:
            tem_high = inf[1].find('span').string  # 找到最高气温
        temp.append(tem_low[:-1])  # 最低气温，去除单位‘°C’

        if str(tem_high)[-1] != '℃':
            temp.append(tem_high)  # 最高气温
        else:
            temp.append(tem_high[:-1])  # 最高气温，去除单位‘°C’

        wind = inf[2].find_all('span')  # 找到风向
        for j in wind:
            temp.append(j['title'])  # 风向
        wind_scale = inf[2].find('i').string  # 找到风级
        index1 = wind_scale.index('级')
        temp.append(int(wind_scale[index1 - 1:index1]))  # 风级
        final.append(temp)
        i = i + 1
    return final


def get_content2(html, city):
    """
    提取HTML内容中的天气数据（8-15天）
    :param html: HTML内容
    :param city: 城市名称
    :return: 返回一个列表，天气数据列表，每个元素为包含城市、日期、天气、最低气温、最高气温、风向1、风向2、风级的子列表
    """
    final = []  # 初始化一个列表保存数据
    bs = BeautifulSoup(html, "html.parser")  # 创建BeautifulSoup对象
    body = bs.body
    data = body.find('div', {'id': '15d'})  # 找到div标签且id = 15d
    ul = data.find('ul')  # 找到所有的ul标签
    li = ul.find_all('li')  # 找到左右的li标签
    for day in li:  # 遍历找到的每一个li if i &lt; 8:
        temp = [city]  # 临时存放每天的数据
        date = day.find('span', {'class': 'time'}).string  # 得到日期
        date = date[date.index('（') + 1:-2]  # 取出日期号
        temp.append(date)
        weather = day.find('span', {'class': 'wea'}).string  # 找到天气
        temp.append(weather)
        tem = day.find('span', {'class': 'tem'}).text  # 找到温度
        temp.append(tem[tem.index('/') + 1:-1])  # 找到最低气温
        temp.append(tem[:tem.index('/') - 1])  # 找到最高气温
        wind = day.find('span', {'class': 'wind'}).string  # 找到风向
        if '转' in wind:  # 如果有风向变化
            temp.append(wind[:wind.index('转')])
            temp.append(wind[wind.index('转') + 1:])
        else:  # 如果没有风向变化，前后风向一致
            temp.append(wind)
            temp.append(wind)
        wind_scale = day.find('span', {'class': 'wind1'}).string  # 找到风级
        index1 = wind_scale.index('级')
        temp.append(int(wind_scale[index1 - 1:index1]))
        final.append(temp)
    return final


def write_to_csv(file_name, data):
    """
    将数据写入CSV文件
    :param file_name:CSV文件名
    :param data: 数据列表
    """
    with open(file_name, 'a', errors='utf-8', newline='') as f:  # 以追加模式打开CSV文件
        f_csv = csv.writer(f)  # 创建CSV写入器
        f_csv.writerows(data)  # 将数据写入CSV文件


def main():
    # 读取城市代码
    city_code = pd.read_table('34个省会城市代码.txt', delimiter=',', names=['城市', '代码'])
    print(city_code.head())

    # 向csv文件写入表头
    header = ['城市', '日期', '天气', '最低气温', '最高气温', '风向1', '风向2', '风级']
    with open('weather15.csv', 'w', errors='ignore', newline='') as f:  # 创建并打开CSV文件
        f_csv = csv.writer(f)  # 创建CSV写入器
        f_csv.writerow(header)  # 写入表头

    # 查询每个省的十五天的天气
    for row in city_code.itertuples(index=False):
        city, code = row

        # city = input('请输入要查询的城市：')
        # code = str(city_code[city_code['城市'] == city]['代码'].values)[1:-1]  # 获取城市代码

        url1 = f'http://www.weather.com.cn/weather/{code}.shtml'  # 7天天气中国天气网
        url2 = f'http://www.weather.com.cn/weather15d/{code}.shtml'  # 8-15天天气中国天气网
        html1 = getHTMLtext(url1)  # 获取网页内容
        data1_7 = get_content(html1, city)  # 获得1-7天和当天的数据
        html2 = getHTMLtext(url2)  # 获取网页内容
        data8_14 = get_content2(html2, city)  # 获得8-14天数据
        data14 = data1_7 + data8_14
        print(data14)
        write_to_csv('weather15.csv', data14)  # 保存为csv文件


if __name__ == '__main__':
    main()
